// type FnIntersectionToTuple<T> = T extends {
//     (x: infer A): void;
//     (x: infer B): void;
// } ? [A, B] : never;
// type intersection = ((x: number) => void) & ((x: string) => void);
// type UnionToIoF<U> =
//     (U extends any ? (k: (x: U) => void) => void : never) extends
//     ((k: infer I) => void) ? I : never
// type tuple = UnionToIoF<number | string>; 

// // 左边 ((K: string) => void) | ((K: number) => void)  右边 
// type ParamType<T> = T extends (...args: infer X) => any ? X : never;

// // c1类型为number | string
// // let c1: FnIntersectionToTuple<tuple> = ['1', 5]


// // ((k: (x: string) => void) => void) | ((k: (x: number) => void) => void)
// type UnionToOne<T> = ( T extends any ? (k: (x: T) => void) => void : never )
// // ((k: string) => void) | ((k: number) => void)
// type UnionToOne2<T> = ( T extends any ? (k: T) => void : never )

// // ((x: string) => void) & ((x: number) => void)
// type UnionToTwo<T> = UnionToOne<T> extends ((k: infer Y)=>void) ? Y: never;

// type UnionToThree<T> = UnionToTwo<T> extends { (x: infer X); (x: infer Y) } ? [X, Y]: never
// let c1: UnionToTwo<number | string>


// type Bar<T> = T extends { a: (x: infer U) => void, b: (x: infer Z) => void } ? [U, Z] : never;
// // type T20 = Bar<{ a: (x: string) => void, b: (x: string) => void }>;  // string
// type T21 = Bar<{ a: (x: string) => void, b: (x: number) => void }>;  // string & number


// type Naked<T> = T extends boolean ? "Y" : "N";
// type Wrapped<T> = [T] extends infer X ? X : "N";

// // "N" | "Y"
// type Result1 = Naked<number | boolean>;

// // "N"
// type Result2 = Wrapped<number | boolean>;

// type A = ((() => string) & (() => number))  extends { (): infer R, (): infer S } ? [R, S] : never


// type Test<T> = (T extends any ? (x: (y: T)=>void)=>void : never) 

// type t1 = Test<number | string>

// type Test2 = t1 extends ((x: infer I) => void)  ? I : never

// type UnionToIntersection<U> = 
//   (
//     U extends any 
//       ? (x: U) => void 
//       : never
//   ) extends ((x: infer I) => void) 
//     ? I 
//     : never

// type I = UnionToIntersection<{a: number} | {b: string}> extends { a: infer X, b: infer Y } ? [X, Y] : never



// type Union<T> = T extends any ? ((x: ()=> T)=> any) : never
// // type UnionToTuple<T> = [T] extends [((x: infer P)  => any)] ? P : never
// type UnionToTuple2 = ((x: ()=>number) => any) | ((x: ()=>string) => any) extends (x: infer P)  => any ? P : never
// type Res3 = UnionToTuple2 extends { (): infer X; (): infer Y } ? [X, Y] : never
// type rs= Union<number | string>

// type UnionToTuple<T> = ((T extends any  ? (x: ()=> T)=> any : never) extends (x: infer P)  => any ? P : never) extends { (): infer X; (): infer Y } ? [X, Y] : never
// type Res = UnionToTuple<number | string>

// class User {
//     name: string;
//     age: number;
//     action: ()=> void;
//     private hobby: ()=> string;
//     protected eye: string
// }

// type usertype = keyof User;  // name | age | action
// // let t1: usertype = "hobby" // 出错
// // let t1: usertype = "eye" // 出错

// type K1 = keyof { [x: symbol]: User }; // symbol
// type K2 = keyof { [x: number]: User }; // nuumber
// type K3 = keyof { [x: string]: User }; // string | number



/*
type _A = {
    a: string;
    b: number;
}
*/
// type _A = typeof A

// interface B {
//     a: ()=>void,
//     b: number
// }
// let b: B = {
//     a: ()=>{
//         console.log('111');
//     },
//     b: 10
// }
// type _B = typeof b

// class C {
//     a: number
//     b: string
// }

// type _C = typeof C 
// let c: _C = C  // emmm.... 感觉好像没什么意义

// // 使用枚举限定日期
// enum day { Mon, Tue, Wed, Thu, Fri, Sat, Sun}
// type _day = typeof day;
// let days: _day = {
//     Mon: 4,
//     Tue: 12,
//     Wed: 1, 
//     Thu: 1, 
//     Fri: 1, 
//     Sat: 1, 
//     Sun: 1
// }
// console.log(days); // { Mon: 4, Tue: 12, Wed: 1, Thu: 1, Fri: 1, Sat: 1, Sun: 1 }


// function compare(x: number, y: number):boolean {
//     return x > y;
// }
// type _compare = typeof compare;  // (x: number, y: number) => boolean

// type A = {
//     name: number;
//     age: number;
// }
// type User = {
//     [K in keyof A]: string
// }

// 筛选出两个 interface 的公共成员
// interface PersonA{
//     name: string
//     age: number
//     boyfriend: string
//     car: {
//       type: 'Benz'
//     }
// }
  
// interface PersonB{
//     name: string
//     age: string
//     girlfriend: string
//     car: {
//         type: 'bicycle'
//     }
// }

// type common<A, B> = A extends B ? A : never;

// type Filter<A, B> = {
//     [ K in common<keyof A, keyof B>]: A[K] extends B[K] ? A[K] :  A[K]|B[K]
// }

// type t = Filter<PersonA, PersonB>
// type z = common<keyof PersonA, keyof PersonB>





// function f(a: number, b: number): number;
// function f(a: string, b: string): string;
// function f(a: string | number, b: string | number): number | string {
//     if (typeof a === 'string' || typeof b === 'string') {
//       return a + ':' + b; // no error but b can be number!
//     } else {
//       return a + b; // error as b can be number | string
//     }
// }

// console.log(f(1, 2));
// console.log(f(1, '2'));
// console.log(f('1', 2));
// console.log(f('1', '2'));


// type Foo = {
// 	a: number;
// 	b?: string;
// 	c: boolean;
// }

// type choose<T> = {
//     [k in keyof T]?: T[k]
// }
// type SetOptional<T, K extends keyof T> =   choose<Pick<T, K>> & Omit<T, K>


// // 测试用例
// type SomeOptional = SetOptional<Foo, 'a' | 'b'>;

// interface Example {
// 	a: string;
// 	b: string | number;
// 	c: () => void;
// 	d: {};
// }


// type ConditionalPick<T, K> = {
//     [z in keyof T as T[z] extends K ? z : never] : T[z]
// }

// // 测试用例：
// type StringKeysOnly = ConditionalPick<Example, string>;



// type Fn = (a: number, b: string) => number
// type AppendArgument<F , A> = F extends (...args: infer X) => infer Y ? (x: A, ...args: X)=> Y : never
// type FinalFn = AppendArgument<Fn, boolean> 
// (x: boolean, a: number, b: string) => number


// type NaiveFlat<T> = T extends (infer X)[] ? NaiveFlat<X> : T;

// // 测试用例：
// type NaiveResult = NaiveFlat<[['a'], [['b', 'c']], 'D']>
// NaiveResult的结果： "a" | "b" | "c" | "d"

// type PartialFun<T> = {
//     [K in keyof T] ? : T[K]
// }

// type A = {
//     a: number
// }

// type _A = PartialFun<A>
// type _A2 = ReadonlyArray<string>


// type Foo = {
// 	a: number;
// 	b?: string;
// 	c: boolean;
// }

// // 对应的属性变成可选
// type CommonFun<T, K> = {
//     [ t in keyof T as t extends K ? t: never] ?: T[t]
// }
// type Unequal<T, K> = {
//     [ t in keyof T as t extends K ? never: t] : T[t]
// }

// type SetOptional<T, K extends keyof T> = Partial<Pick<T, K>> & Omit<T, K> 

// // 测试用例
// type SomeOptional = SetOptional<Foo, 'a' | 'b'>;


// let s: SomeOptional = {
//     a: 4,
//     c: true
// }

// type ArrType = [ number, [string], [ boolean, [ void, string ] ] ]

// type SetOptional<T> = T extends (infer X)[] ? SetOptional<X> : T

// type Res = SetOptional<ArrType>



const createState = () => {
    const store = {
        loading: true
    }
    return store
};
type userState = ReturnType<typeof createState>
let mo = {
    "user": {
        "namespaced": true,
        "state": {
            "loading": true
        },
        "getters": {
            isLogin: (state: userState): string => {
                return `⚪ ${state.loading}`
            }
        },
        "mutations": {},
        "actions": {}
    },
    "wechat": {
        "namespaced": true,
        "state": {
            "loading": true
        },
        "getters": {
            isLogin: (state: userState): number => {
                return 123;
            }
        },
        "mutations": {},
        "actions": {}
    }
}

// let res = mo.user.getters.isLogin({ loading: true });
// console.log(res);


/*
{
    "user/isLogin": string;
    "wechat/isLogin": number;
}
*/ 

type _mo = typeof mo;

type GetterInfo<T> = {
    [k in keyof T]: T[k] extends { 'getters': infer X } ? X: never
}

// 去除user和wechat中getters以外的属性
type GetGetters = GetterInfo<_mo>

// 获得 'user/getters'|'wechat/getters'
type addPrefix<P, K> = `${P & string}/${K & string}`
type GetSpliceKeys<T extends keyof K, K> = T extends string ? addPrefix<T, keyof K[T]>: never

type KeysGetter = GetSpliceKeys<keyof GetGetters, GetGetters>  // "user/isLogin" | "wechat/isLogin"
// 获得GetGetters中user和wechat的getters返回值类型
type getReturnType<T, A, B> = T[A & keyof T][B & keyof T[A & keyof T]] extends (...any)=> infer X ? X : never
// 得到最终结果
type Getter = {
    [k in KeysGetter] : k extends `${infer X}/${infer Y}` ? getReturnType<GetGetters, X, Y> : never
}

